package io.boot.modules.monitor.task;

import com.alibaba.fastjson.JSON;
import io.boot.common.utils.Constant;
import io.boot.common.utils.DateUtils;
import io.boot.modules.job.task.ITask;
import io.boot.modules.monitor.dto.NetVO;
import io.boot.modules.monitor.server.WebSocketNetServer;
import org.hyperic.sigar.NetInterfaceConfig;
import org.hyperic.sigar.NetInterfaceStat;
import org.hyperic.sigar.Sigar;
import org.hyperic.sigar.SigarException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Objects;

/**
 * @author kyson
 * @date 2020/04/24 22:36
 * 网络net流量定时任务
 */
@Component("NetScheduleTask")
public class NetScheduleTask implements ITask {
    protected static final Logger LOGGER = LoggerFactory.getLogger(NetScheduleTask.class);
    @Resource
    private RedisTemplate redisTemplate;

    @Autowired
    private WebSocketNetServer webSocketNetServer;

    /**
     *  执行
     */
    @Override
    public void run(String params){
        //格式化  yyyy-MM-dd HH:mm:ss
        String date=DateUtils.format(new Date(),"HH:mm:ss");
        // 获取当前时间下的网络状态
        NetVO net = null;
        try{
            net = net();
        }catch (Exception e){
            LOGGER.error("定时任务异常：{}", e.getMessage());
            return;
        }
        net.setCurrentTime(date);
        // 取出redis数据
        Long size = redisTemplate.opsForList().size(Constant.MONITOR_NET);
        if(Objects.isNull(size) || 0 == size){
            // 说明list为空
            net.setCurrentRxPackets(Constant.ZERO_LONG);
            net.setCurrentTxPackets(Constant.ZERO_LONG);
            net.setCurrentRxBytes(Constant.ZERO_LONG);
            net.setCurrentTxBytes(Constant.ZERO_LONG);
            redisTemplate.opsForList().leftPush(Constant.MONITOR_NET, JSON.toJSONString(net));
            return;
        }
        // 小于限制的长度时，取出最后一个：计算本次取数
        Object index = redisTemplate.opsForList().index(Constant.MONITOR_NET, Constant.ZERO_LONG);
        NetVO netVO = JSON.parseObject(index.toString(), NetVO.class);
        net.setCurrentRxPackets(net.getRxPackets() - netVO.getRxPackets());
        net.setCurrentTxPackets(net.getTxPackets() - netVO.getTxPackets());
        net.setCurrentRxBytes(net.getRxBytes() - netVO.getRxBytes());
        net.setCurrentTxBytes(net.getTxBytes() - netVO.getTxBytes());
        redisTemplate.opsForList().leftPush(Constant.MONITOR_NET, JSON.toJSONString(net));
        // 长度限制
        if(Constant.MONITOR_NET_SIZE <= size){
            redisTemplate.opsForList().trim(Constant.MONITOR_NET, Constant.ZERO_LONG, (Constant.MONITOR_NET_SIZE -1));
        }

        webSocketNetServer.sendInfo(JSON.toJSONString(net),"net");

    }

    /**
     * 主机网络信息
     */
    private NetVO net() throws SigarException {
        NetVO netVO = new NetVO();

        long rxPackets = 0L, txPackets = 0L, rxBytes = 0L, txBytes = 0L;
        Sigar sigar = new Sigar();
        String ifNames[] = sigar.getNetInterfaceList();
        for (int i = 0; i < ifNames.length; i++) {
            String name = ifNames[i];
            NetInterfaceConfig ifconfig = sigar.getNetInterfaceConfig(name);
            if ((ifconfig.getFlags() & 1L) <= 0L) {
                continue;
            }
            NetInterfaceStat ifstat = sigar.getNetInterfaceStat(name);
            // 接收的总包裹数
            rxPackets += ifstat.getRxPackets();
            // 发送的总包裹数
            txPackets += ifstat.getTxPackets();
            //接收到的总字节数
            rxBytes += ifstat.getRxBytes();
            //发送的总字节数
            txBytes += ifstat.getTxBytes();
        }
        netVO.setRxPackets(rxPackets);
        netVO.setTxPackets(txPackets);
        netVO.setRxBytes(rxBytes/1024/5);
        netVO.setTxBytes(txBytes/1024/5);
        return netVO;
    }

    /**
     *  是否window运行，true代表window
     */
    public static boolean isLocal(){
        return System.getProperties().getProperty("os.name").toUpperCase().contains("WINDOWS");
    }


}
